package com.chinaunicom.emergency.util;

import com.chinaunicom.emergency.exception.CheckException;
import io.minio.MinioClient;
import io.minio.ObjectStat;
import io.minio.errors.*;
import io.minio.http.Method;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

@Log4j2
public class MinioUtil {

    private static String urls;
    private static String accessKey;
    private static String secretKey;
    private static MinioClient minioClients = null;

    static {
        if (ConfigUtil.get("system.minio.urls") != null) {
            urls = ConfigUtil.get("system.minio.urls");
            accessKey = ConfigUtil.get("system.minio.accessKey");
            secretKey = ConfigUtil.get("system.minio.secretKey");
            try {
                init();
            } catch (Exception e) {
                log.error("初始化minio错误", e);
            }
        }

    }

    public static MinioClient getAvailableMinioClient() throws CheckException {
        if (minioClients != null) {
            return minioClients;
        }
        throw new CheckException("未找到可用的minio服务");
    }

    public static boolean init() {
        String url = urls;
        try {
            minioClients = new MinioClient(url, accessKey, secretKey);
            minioClients.setTimeout(10000, 999999999, 999999999);
            String attr = ConfigUtil.get("system.minio.bucket.attr");
            if (StringUtils.isNotBlank(attr) && !minioClients.bucketExists(attr)) {
                minioClients.makeBucket(attr);
            }
            String version = ConfigUtil.get("system.minio.bucket.rn.version");
            if (StringUtils.isNotBlank(version) && !minioClients.bucketExists(version)) {
                minioClients.makeBucket(version);
            }
        } catch (Exception e) {
            log.error("mini连接失败," + url, e);
        }
        return true;
    }

    public static void put(String bucketName, String objectName, InputStream in, long size, String contentType) throws CheckException {
        MinioClient minioClient = getAvailableMinioClient();
        try {
            // Check if the bucket already exists.
            boolean isExist = minioClient.bucketExists(bucketName);
            if (!isExist) {
                minioClient.makeBucket(bucketName);
            }

            // Upload the zip file to the bucket with putObject
            minioClient.putObject(bucketName, objectName, in, size, contentType);
            log.info("上传{}完成,objectName={}", bucketName, objectName);
        } catch (Exception e) {
            log.error("Minio上传失败", e);
            throw new CheckException("Minio上传失败！请重试");
        }
    }

    public static void put(String bucketName, String objectName, InputStream in, long size) throws CheckException {
        put(bucketName, objectName, in, size, "application/octet-stream");
    }

    public static String getUrl(String bucketName, String objectName) throws CheckException {
        MinioClient minioClient = getAvailableMinioClient();
        try {
            return minioClient.getObjectUrl(bucketName, objectName);
        } catch (Exception e) {
            log.error("获取文件失败", e);
            throw new CheckException("获取文件失败！请重试");
        }
    }

    public static ObjectStat statObject(String bucketName, String objectName) throws CheckException {
        MinioClient minioClient = getAvailableMinioClient();

        try {
            ObjectStat objectStat = minioClient.statObject(bucketName, objectName);
            return objectStat;
        } catch (Exception e) {
            log.error("获取文件失败", e);
            throw new CheckException("获取文件失败！请重试");
        }
    }


    public static InputStream get(String bucketName, String objectName) throws CheckException {
        MinioClient minioClient = getAvailableMinioClient();

        try {
            InputStream in = minioClient.getObject(bucketName, objectName);
            return in;
        } catch (Exception e) {
            log.error("获取文件失败", e);
            throw new CheckException("获取文件失败！请重试");
        }
    }

    public static InputStream get(String bucketName, String objectName, long offset) throws CheckException {
        MinioClient minioClient = getAvailableMinioClient();

        try {
            InputStream in = minioClient.getObject(bucketName, objectName, offset);
            return in;
        } catch (Exception e) {
            log.error("获取文件失败", e);
            throw new CheckException("获取文件失败！请重试");
        }
    }

    public static InputStream get(String bucketName, String objectName, long offset, long length) throws CheckException {
        MinioClient minioClient = getAvailableMinioClient();

        try {
            InputStream in = minioClient.getObject(bucketName, objectName, offset, length);
            return in;
        } catch (Exception e) {
            log.error("获取文件失败", e);
            throw new CheckException("获取文件失败！请重试");
        }
    }

    public static String getObjUrl(String bucketName, String objectName) throws CheckException {
        MinioClient minioClient = getAvailableMinioClient();
        try {
            return minioClient.getPresignedObjectUrl(Method.GET, bucketName, objectName, 60 * 60 * 10, null);
        } catch (Exception e) {
            log.error("获取文件失败", e);
            throw new CheckException("获取文件失败！请重试");
        }
    }

    public static String getDownloadObjUrl(String bucketName, String objectName,String contentDisposition) throws CheckException {
        MinioClient minioClient = getAvailableMinioClient();
        try {
            Map<String,String> reqHeader = new HashMap<>();
            reqHeader.put("response-content-disposition",contentDisposition);
            reqHeader.put("content-disposition",contentDisposition);
            return minioClient.getPresignedObjectUrl(Method.GET, bucketName, objectName, 60 * 60 * 10, reqHeader);
        } catch (Exception e) {
            log.error("获取文件失败", e);
            throw new CheckException("获取文件失败！请重试");
        }
    }

    public static void delete(String bucketName, String objectName) throws CheckException {
        MinioClient minioClient = getAvailableMinioClient();

        try {
            minioClient.removeObject(bucketName, objectName);
        } catch (Exception e) {
            log.error("删除文件失败", e);
            throw new CheckException("删除文件失败！请重试");
        }
    }
}
